{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "What is PyTorch?\n",
    "================\n",
    "\n",
    "It’s a Python based scientific computing package targeted at two sets of\n",
    "audiences:\n",
    "\n",
    "-  A replacement for NumPy to use the power of GPUs\n",
    "-  a deep learning research platform that provides maximum flexibility\n",
    "   and speed\n",
    "\n",
    "Getting Started\n",
    "---------------\n",
    "\n",
    "Tensors\n",
    "^^^^^^^\n",
    "\n",
    "Tensors are similar to NumPy’s ndarrays, with the addition being that\n",
    "Tensors can also be used on a GPU to accelerate computing.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Construct a 5x3 matrix, uninitialized:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0000e+00,  0.0000e+00,  4.7278e-05],\n",
      "        [ 4.5618e-41,  1.4409e+02,  4.5618e-41],\n",
      "        [ 1.5302e-38,  0.0000e+00,  1.5301e-38],\n",
      "        [ 0.0000e+00,  7.0948e+22,  3.6448e-42],\n",
      "        [ 8.9683e-44,  0.0000e+00,  1.6314e+02]])\n",
      "torch.Size([5, 3])\n"
     ]
    }
   ],
   "source": [
    "x = torch.empty(5, 3)\n",
    "print(x)\n",
    "x.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Construct a randomly initialized matrix:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.3459,  0.0258,  0.8485],\n",
      "        [ 0.6488,  0.6691,  0.2285],\n",
      "        [ 0.7729,  0.5476,  0.0136],\n",
      "        [ 0.7078,  0.7097,  0.2029],\n",
      "        [ 0.1760,  0.1377,  0.1179]])\n"
     ]
    }
   ],
   "source": [
    "x = torch.rand(5, 3)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Construct a matrix filled zeros and of dtype long:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0,  0,  0],\n",
      "        [ 0,  0,  0],\n",
      "        [ 0,  0,  0],\n",
      "        [ 0,  0,  0],\n",
      "        [ 0,  0,  0]])\n"
     ]
    }
   ],
   "source": [
    "x = torch.zeros(5, 3, dtype=torch.long)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Construct a tensor directly from data:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 5.5000,  3.0000])\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([5.5, 3])\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or create a tensor basing on existing tensor. These methods\n",
    "will reuse properties of the input tensor, e.g. dtype, unless\n",
    "new values are provided by user\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.,  1.,  1.],\n",
      "        [ 1.,  1.,  1.],\n",
      "        [ 1.,  1.,  1.],\n",
      "        [ 1.,  1.,  1.],\n",
      "        [ 1.,  1.,  1.]], dtype=torch.float64)\n",
      "tensor([[-0.0651, -1.9033, -0.4527],\n",
      "        [ 0.4042,  0.8015,  0.2316],\n",
      "        [-0.0526,  0.8932,  1.0476],\n",
      "        [ 0.5796,  0.6212, -0.8285],\n",
      "        [ 1.0648, -0.4679,  1.5079]])\n"
     ]
    }
   ],
   "source": [
    "x = x.new_ones(5, 3, dtype=torch.double)      # new_* methods take in sizes\n",
    "print(x)\n",
    "\n",
    "x = torch.randn_like(x, dtype=torch.float)    # override dtype!\n",
    "print(x)                                      # result has the same size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get its size:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([5, 3])\n"
     ]
    }
   ],
   "source": [
    "print(x.size())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\"><h4>Note</h4><p>``torch.Size`` is in fact a tuple, so it supports all tuple operations.</p></div>\n",
    "\n",
    "Operations\n",
    "^^^^^^^^^^\n",
    "There are multiple syntaxes for operations. In the following\n",
    "example, we will take a look at the addition operation.\n",
    "\n",
    "Addition: syntax 1\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0523, -1.4376,  0.5227],\n",
      "        [ 0.7721,  1.2392,  1.1539],\n",
      "        [ 0.1719,  1.6686,  1.7931],\n",
      "        [ 0.9792,  1.1205,  0.0044],\n",
      "        [ 2.0217, -0.3347,  2.3685]])\n"
     ]
    }
   ],
   "source": [
    "y = torch.rand(5, 3)\n",
    "print(x + y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Addition: syntax 2\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0523, -1.4376,  0.5227],\n",
      "        [ 0.7721,  1.2392,  1.1539],\n",
      "        [ 0.1719,  1.6686,  1.7931],\n",
      "        [ 0.9792,  1.1205,  0.0044],\n",
      "        [ 2.0217, -0.3347,  2.3685]])\n"
     ]
    }
   ],
   "source": [
    "print(torch.add(x, y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Addition: providing an output tensor as argument\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0523, -1.4376,  0.5227],\n",
      "        [ 0.7721,  1.2392,  1.1539],\n",
      "        [ 0.1719,  1.6686,  1.7931],\n",
      "        [ 0.9792,  1.1205,  0.0044],\n",
      "        [ 2.0217, -0.3347,  2.3685]])\n"
     ]
    }
   ],
   "source": [
    "result = torch.empty(5, 3)\n",
    "torch.add(x, y, out=result)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Addition: in-place\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0523, -1.4376,  0.5227],\n",
      "        [ 0.7721,  1.2392,  1.1539],\n",
      "        [ 0.1719,  1.6686,  1.7931],\n",
      "        [ 0.9792,  1.1205,  0.0044],\n",
      "        [ 2.0217, -0.3347,  2.3685]])\n"
     ]
    }
   ],
   "source": [
    "# adds x to y\n",
    "y.add_(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\"><h4>Note</h4><p>Any operation that mutates a tensor in-place is post-fixed with an ``_``.\n",
    "    For example: ``x.copy_(y)``, ``x.t_()``, will change ``x``.</p></div>\n",
    "\n",
    "You can use standard NumPy-like indexing with all bells and whistles!\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([-1.9033,  0.8015,  0.8932,  0.6212, -0.4679])\n"
     ]
    }
   ],
   "source": [
    "print(x[:, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Resizing: If you want to resize/reshape tensor, you can use ``torch.view``:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = torch.randn(4, 4)\n",
    "y = x.view(16)\n",
    "z = x.view(-1, 8)  # the size -1 is inferred from other dimensions\n",
    "print(x.size(), y.size(), z.size())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you have a one element tensor, use ``.item()`` to get the value as a\n",
    "Python number\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = torch.randn(1)\n",
    "print(x)\n",
    "print(x.item())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Read later:**\n",
    "\n",
    "\n",
    "  100+ Tensor operations, including transposing, indexing, slicing,\n",
    "  mathematical operations, linear algebra, random numbers, etc.,\n",
    "  are described\n",
    "  `here <http://pytorch.org/docs/torch>`_.\n",
    "\n",
    "NumPy Bridge\n",
    "------------\n",
    "\n",
    "Converting a Torch Tensor to a NumPy array and vice versa is a breeze.\n",
    "\n",
    "The Torch Tensor and NumPy array will share their underlying memory\n",
    "locations, and changing one will change the other.\n",
    "\n",
    "Converting a Torch Tensor to a NumPy Array\n",
    "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = torch.ones(5)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = a.numpy()\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See how the numpy array changed in value.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a.add_(1)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Converting NumPy Array to Torch Tensor\n",
    "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
    "See how changing the np array changed the Torch Tensor automatically\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = np.ones(5)\n",
    "b = torch.from_numpy(a)\n",
    "np.add(a, 1, out=a)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All the Tensors on the CPU except a CharTensor support converting to\n",
    "NumPy and back.\n",
    "\n",
    "CUDA Tensors\n",
    "------------\n",
    "\n",
    "Tensors can be moved onto any device using the ``.to`` method.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# let us run this cell only if CUDA is available\n",
    "# We will use ``torch.device`` objects to move tensors in and out of GPU\n",
    "if torch.cuda.is_available():\n",
    "    device = torch.device(\"cuda\")          # a CUDA device object\n",
    "    y = torch.ones_like(x, device=device)  # directly create a tensor on GPU\n",
    "    x = x.to(device)                       # or just use strings ``.to(\"cuda\")``\n",
    "    z = x + y\n",
    "    print(z)\n",
    "    print(z.to(\"cpu\", torch.double))       # ``.to`` can also change dtype together!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
